home *** CD-ROM | disk | FTP | other *** search
- /* "Dumb terminal" mailbox interface
- * Copyright 1991 Phil Karn, KA9Q
- *
- * May '91 Bill Simpson
- * move to separate file for compilation & linking
- * Sep '91 Bill Simpson
- * minor changes for DTR & RLSD
- * Jan '93 Doug Crompton
- * Mods to code to make it work with both terminal
- * and Modem. Timers and CD check revamped. Now Always
- * detects CD loss and timeouts work properly.
- * Setting Tiptimeout to 0 disables idle and CD loss check
- *
- * Command Syntax now : 'start tip <interface> <modem|terminal>'
- */
- #include "global.h"
- #include "commands.h"
- #include "mbuf.h"
- #include "timer.h"
- #include "proc.h"
- #include "iface.h"
- #ifdef UNIX
- #include "unixasy.h"
- #else
- #include "n8250.h"
- #endif
- #include "asy.h"
- #include "usock.h"
- #include "telnet.h"
- #include "mailbox.h"
- #include "devparam.h"
-
- #if !defined(_lint)
- static char rcsid[] OPTIONAL = "$Id: tipmail.c,v 1.24 1997/08/19 01:19:22 root Exp root $";
- #endif
-
- #if defined(TIPMAIL) || defined(ALLSERV)
-
- static struct tipcb *Tiplist;
- struct suspended *Tipsuspended;
-
- static void tip_in (int dev, void *n1, void *n2);
- static void tipidle (void *t);
- void suspendTipMail (struct mbx * m);
-
- unsigned Tiptimeout = 180; /* Default tip inactivity timeout (seconds) */
-
-
- /* Input process */
- static void
- tip_in (int dev, void *n1, void *n2 OPTIONAL)
- {
- struct tipcb *tip;
- struct mbuf *bp;
- const char *buf[2];
- char line[MBXLINE];
- int c, ret, pos = 0;
-
- line[0] = 0;
- tip = (struct tipcb *) n1;
- while ((c = get_asy (dev)) != -1) {
- tip->firstwarn = 1;
- tip->timeout = tip->default_timeout;
- Asy[dev].iface->lastrecv = secclock ();
-
- if (!tip->raw) {
- c &= 0x7f;
- ret = 0;
- if (tip->echo == WONT) {
- switch (c) {
- case 18: /* CTRL-R */
- bp = pushdown (qdata ((unsigned char *) line, (int16) pos), 4);
- #ifndef TNOS_68K
- memcpy (bp->data, "^R\r\n", 4);
- #else
- memcpy (bp->data, "^R\r\l", 4);
- #endif
- ret = 1;
- break;
- case 0x7f: /* DEL */
- case '\b':
- bp = NULLBUF;
- if (pos) {
- --pos;
- bp = qdata ((const unsigned char *) "\b \b", 3);
- }
- ret = 1;
- break;
- #ifndef TNOS_68K
- case '\r':
- #else
- case '\l':
- #endif
- c = '\n'; /* CR => NL */
- case '\n':
- #ifndef TNOS_68K
- bp = qdata ((const unsigned char *) "\r\n", 2);
- #else
- bp = qdata ("\r\l", 2);
- #endif
- break;
- default:
- bp = pushdown (NULLBUF, 1);
- *bp->data = uchar (c);
- break;
- }
- (void) asy_send (dev, bp);
- tip->iface->lastsent = secclock ();
- if (ret)
- continue;
- }
- line[pos++] = (char) c;
- if (pos == MBXLINE - 1 || tip->echo == WILL || c == '\n') {
- line[pos] = '\0';
- pos = 0;
- usputs (tip->s, line);
- usflush (tip->s);
- }
- } else {
- usputc (tip->s, uchar (c));
- usflush (tip->s);
- }
- }
- /* get_asy() failed, terminate */
- close_s (tip->s);
- tip->in = tip->proc;
- tip->proc = Curproc;
- buf[1] = Asy[dev].iface->name;
- (void) tip0 (2, buf, NULL);
- }
-
-
-
- /* Start mailbox on serial line */
- int
- tipstart (int argc, char *argv[], void *p)
- {
- register struct iface *ifp;
- register struct asy *ap;
- register struct tipcb *tip;
- struct mbuf *bp, *dp, *op; /* op is output, dp is duplicate */
- char const *buf[2];
- int dev, c, i, off, cnt, cmd, s[2], type = TIP;
- #ifndef UNIX
- struct fifo *fp;
- #endif
-
- if ((ifp = if_lookup (argv[1])) == NULLIF) {
- tprintf (Badinterface, argv[1]);
- return 1;
- }
- for (dev = 0, ap = Asy; dev < ASY_MAX; dev++, ap++)
- if (ap->iface == ifp)
- break;
- if (dev == ASY_MAX) {
- tprintf ("Interface %s not asy port\n", argv[1]);
- return 1;
- }
- if (ifp->raw == bitbucket) {
- tprintf ("Tip session already active on %s\n", argv[1]);
- return 1;
- }
- ksignal (Curproc, 0); /* Don't keep the parser waiting */
- chname (Curproc, "PBBS tip");
- tip = (struct tipcb *) callocw (1, sizeof (struct tipcb));
-
- if (argc > 2 && *argv[2] == 'm')
- tip->modem = 1;
- tprintf ("Tip started on %s - with%s CD check - ", argv[1], (tip->modem) ? "" : "out");
- tip->default_timeout = (argc > 3) ? (unsigned) atoi (argv[3]) : Tiptimeout;
- if (tip->default_timeout)
- tprintf ("%d Second", tip->default_timeout);
- else
- tputs ("No");
- tputs (" Timeout\n");
-
-
- /* Save output handler and temporarily redirect output to null */
- tip->asy_dev = dev;
- tip->rawsave = ifp->raw;
- ifp->raw = bitbucket;
- tip->iface = ifp;
- tip->proc = Curproc;
- tip->timer.func = tipidle;
- tip->timer.arg = (void *) tip;
- tip->raw = 0;
- tip->next = Tiplist;
- Tiplist = tip;
- buf[1] = ifp->name;
-
- /* Suspend packet input drivers */
- suspend (ifp->rxproc);
-
- for (;;) {
- (void) ifp->ioctl (ifp, PARAM_UP, TRUE, 0L);
- /* Wait for DCD to be asserted if modem */
- if (tip->modem) {
- kpause (1000);
- #ifndef MSDOS
- while (!carrier_detect (tip->asy_dev))
- kwait (NULL);
- kpause (1000L);
- #endif
- }
- if (socketpair (AF_LOCAL, SOCK_STREAM, 0, s) == -1) {
- tprintf ("Could not create socket pair, errno %d\n", errno);
- (void) tip0 (2, buf, p);
- return 1;
- }
- (void) seteol (s[0], "\n");
- (void) seteol (s[1], "\n");
- tip->echo = WONT;
- tip->s = s[0];
- if (tip->modem)
- log (tip->s, "Phone Mailbox Login");
- (void) newproc ("pbbs_incom", 2048, pbbs_incom, s[1], (void *) type, (void *) tip, 0);
-
- /* check for line idle timeout and CD failure */
- tip->firstwarn = 1;
- tip->timeout = tip->default_timeout;
- set_timer (&tip->timer, 1000L);
- start_timer (&tip->timer);
-
- (void) setflush (tip->s, -1);
- (void) sockmode (tip->s, SOCK_ASCII);
-
- /* Now fork into two paths, one rx, one tx */
- #ifndef UNIX
- /* first clear (ignore) junk in asyinc input
- which is always receiving - modem can garbage
- on disconnect
- */
- fp = &ap->fifo;
- fp->wp = fp->rp = fp->buf;
- fp->cnt = 0;
- #endif
-
- tip->in = newproc ("PBBS tip in", 256, tip_in, dev, (void *) tip, NULL, 0);
- while ((cnt = recv_mbuf (tip->s, &bp, 0, NULL, 0)) != -1) {
- if (!tip->raw) {
- (void) dup_p (&dp, bp, off = 0, (int16) cnt); /* dup the whole pkt to pull */
- for (i = 0; i < cnt; i++)
- switch (PULLCHAR (&dp)) { /*lint !e506 */
- case IAC: /* ignore most telnet options */
- (void) dup_p (&op, bp, (int16) off, (int16) (i - off));
- (void) asy_send (dev, op);
- ifp->lastsent = secclock ();
-
- if ((cmd = ++i < cnt ? PULLCHAR (&dp) : recvchar (tip->s)) == EOF) /*lint !e506 */
- break;
- if (cmd > 250 && cmd < 255) {
- if ((c = ++i < cnt ? PULLCHAR (&dp) : recvchar (tip->s)) == EOF) /*lint !e506 */
- break;
- switch (cmd) {
- case WILL:
- if (c == TN_ECHO) {
- tip->echo = cmd;
- cmd = DO;
- } else
- cmd = DONT;
- break;
- case WONT:
- if (c == TN_ECHO)
- tip->echo = cmd;
- cmd = DONT;
- break;
- case DO:
- case DONT:
- cmd = WONT;
- break;
- default:
- break;
- }
- usprintf (tip->s, "%c%c%c", IAC, cmd, c);
- usflush (tip->s);
- }
- off = i + 1;
- break;
- case '\r':
- if (++i < cnt && /* Skip NL but not IAC */
- (PULLCHAR (&dp) == IAC)) { /*lint !e506 */
- dp = pushdown (dp, 1);
- *dp->data = IAC;
- }
- break;
- #ifndef TNOS_68K
- case '\n':
- #else
- case '\l':
- #endif
- (void) dup_p (&op, bp, (int16) off, (int16)(i - off));
- #ifndef TNOS_68K
- append (&op, qdata ((const unsigned char *) "\r\n", 2));
- #else
- append (&op, qdata ("\r\l", 2));
- #endif
- (void) asy_send (dev, op);
- ifp->lastsent = secclock ();
- off = i + 1;
- break;
- default:
- break;
- }
-
- (void) pullup (&bp, (unsigned char *) 0, (int16) off);
- (void) asy_send (dev, bp);
- } else
- (void) asy_send (dev, bp);
-
- ifp->lastsent = secclock ();
-
- kwait (NULL);
- }
- stop_timer (&tip->timer);
- kpause (2000L);
- close_s (tip->s);
- killproc (tip->in);
- tip->in = NULLPROC;
-
- kwait (itop (s[1])); /* let mailbox terminate, if necessary */
-
- if (!tip->keep && tip->modem) {
- /* Tell line to go down */
- (void) ifp->ioctl (ifp, PARAM_DOWN, TRUE, 0L);
- kpause (5000);
- }
- }
- }
-
-
-
- int
- tip0 (int argc OPTIONAL, char const *argv[], void *p OPTIONAL)
- {
- register struct iface *ifp;
- struct tipcb *tip, *prev = NULLTIP;
- struct proc *proc;
-
- if ((ifp = if_lookup (argv[1])) == NULLIF) {
- tprintf (Badinterface, argv[1]);
- return 1;
- }
- for (tip = Tiplist; tip != NULLTIP; prev = tip, tip = tip->next)
- if (tip->iface == ifp) {
- if (prev != NULLTIP)
- prev->next = tip->next;
- else
- Tiplist = tip->next;
- proc = tip->proc;
- close_s (tip->s);
- ifp->raw = tip->rawsave;
- resume (ifp->rxproc);
- stop_timer (&tip->timer);
- killproc (tip->in);
- free ((char *) tip);
- killproc (proc);
- return 0;
- }
- return 0;
- }
-
-
-
- static void
- tipidle (void *t)
- {
- struct tipcb *tip;
- #ifndef TNOS_68K
- static const char *msg1 = "Line idle - One minute to disconnect...\007\r\n";
- static const char *msg2 = "Disconnecting...\007\r\n";
- #else
- static const char *msg1 = "Line idle - One minute to disconnect...\007\r\l";
- static const char *msg2 = "Disconnecting...\007\r\l";
- #endif
-
- tip = (struct tipcb *) t;
-
- if (tip->modem
- #ifndef MSDOS
- && !carrier_detect (tip->asy_dev)
- #endif
- ) {
- close_s (tip->s);
- return;
- }
- if (tip->default_timeout && (int)(--tip->timeout) <= 0) {
- if (tip->firstwarn) {
- tip->iface->lastsent = secclock ();
- (void) asy_send (tip->iface->dev, qdata ((const unsigned char *) msg1, (int16) strlen (msg1)));
- tip->timeout = 60;
- start_timer (&tip->timer);
- tip->firstwarn = 0;
- } else {
- (void) asy_send (tip->iface->dev, qdata ((const unsigned char *) msg2, (int16) strlen (msg2)));
- close_s (tip->s);
- }
- } else
- start_timer (&tip->timer);
- }
-
-
-
- void
- suspendTipMail (struct mbx *m)
- {
- char const *args[2];
-
- if (m->tip->modem) { /* if modem connect, we can resume */
- /* save the interface in the suspended array, for asytimer() */
- Tipsuspended[m->tip->asy_dev].ifp = m->tip->iface;
- Tipsuspended[m->tip->asy_dev].modem = m->tip->modem;
- Tipsuspended[m->tip->asy_dev].timeout = m->tip->default_timeout;
- m->tip->keep = 1;
- tputs ("Tipmail will resume after you disconnect\n");
- } else
- tputs ("Tipmail terminated on this interface\n");
- usflush (Curproc->output);
- /* now stop the tipmail */
- args[1] = m->tip->iface->name;
- (void) tip0 (2, args, NULL);
- }
- #endif /* ALLSERV || TIPMAIL */
-
-
-
- static int Stelnet = -1;
-
- /* Start up Telnet server */
- int
- telnet1 (int argc, char *argv[], void *p OPTIONAL)
- {
- return (installserver (argc, argv, &Stelnet, "Telnet listener", IPPORT_TELNET,
- INADDR_ANY, "pbbs", pbbs_incom, 2048, (void *) TELNET_LINK));
- }
-
- /* Stop telnet server */
- int
- telnet0 (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
- {
- return (deleteserver (&Stelnet));
- }
-
-
- static int SFBBtelnet = -1;
-
- /* Start up FBB Telnet server */
- int
- fbbtelnet1 (int argc, char *argv[], void *p OPTIONAL)
- {
- return (installserver (argc, argv, &SFBBtelnet, "FBB/Telnet listener", IPPORT_FTELNET,
- INADDR_ANY, "pbbs", pbbs_incom, 2048, (void *) (TELNET_LINK | JUMPSTARTED)));
- }
-
- /* Stop FBB telnet server */
- int
- fbbtelnet0 (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
- {
- return (deleteserver (&SFBBtelnet));
- }
-
-